package com.unionpay.upyzt.net;

import com.unionpay.upyzt.Upyzt;
import com.unionpay.upyzt.exception.APIConnectionException;
import com.unionpay.upyzt.exception.UpyztException;
import com.unionpay.upyzt.net.APIResource.RequestMethod;
import lombok.Getter;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.nio.file.Files;

import static com.unionpay.upyzt.util.StringUtils.CRLF;

@Getter
public class UpyztFileRequest extends UpyztRequest {

    /**
     * 请求图片
     */
    protected File file;

    /**
     * 初始化文件请求
     *
     * @param method  the HTTP method
     * @param url     the URL
     * @param options the options
     * @throws UpyztException if the request cannot be initialized for any reason
     */
    public UpyztFileRequest(
            RequestMethod method,
            String url,
            File file,
            RequestOptions options)
            throws UpyztException {
        super();
        try {
            this.method = method;
            this.options = (options != null) ? options : RequestOptions.getDefault();
            this.url = new URL(url);
            this.file = file;
            this.content = HttpContent.buildFileContent(file);
            this.authorization = buildAuthorization(this.method, this.url, this.content, this.options);
            this.headers = buildHeaders(this.authorization, this.options);
        } catch (IOException e) {
            throw new APIConnectionException(
                    String.format(
                            "请求 Upyzt (%s) 遇到 IO 异常: %s，请检查后再重试",
                            Upyzt.getApiBase(), e.getMessage()),
                    e);
        }
    }

    @Override
    public void writeOutputStream(OutputStream output) throws IOException {
        String boundary = this.content.getBoundary();
        Charset charset = APIResource.CHARSET;
        try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, charset), true)) {
            writer.append("--").append(boundary).append(CRLF);
            writer.append("Content-Disposition: form-data; name=\"meta\"").append(CRLF);
            writer.append("Content-Type: application/json").append(CRLF);
            writer.append(CRLF).append(this.content.getContent()).append(CRLF).flush();
            writer.append("--").append(boundary).append(CRLF);
            writer.append(String.format("Content-Disposition: form-data; name=\"file\"; filename=\"%s\";", this.file.getName())).append(CRLF);
            writer.append("Content-Type: ").append(URLConnection.guessContentTypeFromName(this.file.getName())).append(CRLF);
            writer.append("Content-Transfer-Encoding: binary").append(CRLF);
            writer.append(CRLF).flush();
            Files.copy(file.toPath(), output);
            output.flush();
            writer.append(CRLF).flush();
            writer.append("--").append(boundary).append("--").append(CRLF).flush();
        }
    }
}
